const dbHandler = require("../../../service/dbhandler");
const sipUtils = require("../../../utils/sipUtils");
const log4js = require('../../../utils/logUtils');
const logger = log4js.getLogger('sip');
const deviceCache = require("../../../db/deviceCache");
const config = require("../../../db/config");
const settingModel = require("../../../model/setting");

const TAG = "[InviteFactory]";
/**
 * 生成 invite 请求信令
 */
module.exports={

    /**
     *
     * @param mediaIp
     * @param deviceId
     * @param channelId
     * @param udpPort
     * @param s 播放类型，Play或Playback
     * @param startTime 回放开始时间
     * @param endTime 回放结束时间
     * @return {Promise<{headers: {cseq: {method: string, seq: number}, expires: string, "Max-Forwards": number, subject: string, contact: [{uri: string}], "call-id": string, "User-Agent": string, from: {params: {tag: string}, uri: string}, to: {uri: string}, via: [{protocol: *, port: *, host: *, version: string} & *], "Content-Type": string}, method: string, uri: string, version: string, content: string}|null>}
     */
    invite: async function (mediaIp, deviceId, channelId, udpPort, s='Play',
    startTime=0, endTime=0) {
        if (!deviceId) {
            logger.warn('计算invite时，设备id异常,deviceId', deviceId, 'channelId', channelId);
            return null;
        }
        let ssrc = `${deviceId.substring(13)}${channelId.substring(17)}`;
        const deviceInfo = await dbHandler.loadDevice(deviceId);

        let res;
        if (!deviceInfo || !deviceInfo.channels) {
            logger.warn('计算invite时，设备未注册,deviceid', deviceId, 'channelId', channelId, 'deviceInfo', deviceInfo);
            res = null;
        }else {
            let channelInfo = deviceInfo.channels[channelId];

            if (!channelInfo) {
                logger.error(`计算invite时，设备 ${deviceId} 中没有找到 channel : ${channelId}`, 'deviceInfo', deviceInfo);
                res = null;
            } else {
                let content = 'v=0\r\n' +
                    `o=${channelId} 0 0 IN IP4 ${mediaIp}\r\n` +
                    `s=${s}\r\n` +
                    `c=IN IP4 ${mediaIp}\r\n` +
                    `t=${startTime} ${endTime}\r\n` +
                    `m=video ${udpPort} TCP/RTP/AVP 96 97 98\r\n` +
                    'a=setup:passive\r\n' +
                    'a=rtpmap:96 PS/90000\r\n' +
                    'a=rtpmap:97 MPEG4/90000\r\n' +
                    'a=rtpmap:98 H264/90000\r\n' +
                    'a=recvonly\r\n' +
                    'a=streamprofile:0\r\n' +
                    'a=streamnumber:0\r\n' +
                    `y=${ssrc}\r\n\r\n`
                ;

                // logger.info(TAG, "组合的 invite 信令内容为：", content);
                let cseq = {method: 'INVITE', seq: 1};
                let callId = Math.round((new Date()).getTime() / 1000) + '';

                let via = sipUtils.generateVia(channelInfo.protocol, deviceInfo.via_params);
                res = {
                    method: cseq.method, content,
                    uri: sipUtils.generateUri(channelInfo.deviceid, channelId, null, deviceInfo.sip_command_host, deviceInfo.sip_command_port),
                    version: config.sip.version,
                    headers: {
                        via, cseq,
                        from: {
                            uri: `sip:${settingModel.cache.sip_command_account}@${settingModel.cache.server_realm}`,
                            params: {tag: 'proxy'}
                        },
                        to: {uri: `sip:${channelId}@${settingModel.cache.server_realm}`},
                        'call-id': callId,
                        'Content-Type': 'Application/SDP',
                        'expires': '3600',
                        'Max-Forwards': 70,
                        'User-Agent': config.sip.useragent,
                        contact: sipUtils.buildContact(),
                        subject: `${channelId}:0,${settingModel.cache.sip_command_account}:0`
                    }
                };

                channelInfo.invite = res;
                channelInfo.invite_port = udpPort;
                // logger.info(TAG, "信令包装：", channelInfo);
                deviceCache.registry.invites[callId] = {deviceid: deviceId, channel: channelId};
            }
        }
        return res;
    },
}
